// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © moneymovesalgo
//@version=5

indicator('GG Shot - Decoded', overlay=true)

length = input(title='Period', defval=1)
mult = input.float(title='Multiplier', step=0.1, defval=13)
//ichimoku inputs
conversionPeriods = input.int(9, minval=1, title='Conversion Line Periods')
basePeriods = input.int(26, minval=1, title='Base Line Periods')
laggingSpan2Periods = input.int(52, minval=1, title='Lagging Span 2 Periods')
displacement = input.int(26, minval=1, title='Displacement')

//algo
atr = mult * ta.atr(length)

//kumo
donchian(len) =>
    math.avg(ta.lowest(len), ta.highest(len))
conversionLine = donchian(conversionPeriods)
baseLine = donchian(basePeriods)
leadLine1 = math.avg(conversionLine, baseLine)
leadLine2 = donchian(laggingSpan2Periods)

longStop = hl2 - atr
longStopPrev = nz(longStop[1], longStop)
longStop := close[1] > longStopPrev ? math.max(longStop, longStopPrev) : longStop

shortStop = hl2 + atr
shortStopPrev = nz(shortStop[1], shortStop)
shortStop := close[1] < shortStopPrev ? math.min(shortStop, shortStopPrev) : shortStop

dir = 1
dir := nz(dir[1], dir)
dir := dir == -1 and close > shortStopPrev ? 1 : dir == 1 and close < longStopPrev ? -1 : dir


longColor = color.blue
shortColor = color.blue


////////////////////////////////////////////////////////////    
// Conditions 1

longCond = bool(na)
shortCond = bool(na)
longCond := ta.crossover(close[1], shortStopPrev)
shortCond := ta.crossunder(close[1], longStopPrev)

// Conditions 2

longCond2 = bool(na)
shortCond2 = bool(na)
longCond2 := ta.crossover(close[1], shortStopPrev)
shortCond2 := ta.crossunder(close[1], longStopPrev)

// Conditions 3

longCond3 = bool(na)
shortCond3 = bool(na)
longCond3 := ta.crossover(close[1], shortStopPrev)
shortCond3 := ta.crossunder(close[1], longStopPrev)

////////////////////////////////////////////////////////////    
// Count your long short conditions for more control with Pyramiding

sectionLongs = 0
sectionLongs := nz(sectionLongs[1])
sectionShorts = 0
sectionShorts := nz(sectionShorts[1])

if longCond
    sectionLongs += 1
    sectionShorts := 0
    sectionShorts

if shortCond
    sectionLongs := 0
    sectionShorts += 1
    sectionShorts

// Count your long short conditions for more control with Pyramiding 2

sectionLongs2 = 0
sectionLongs2 := nz(sectionLongs2[1])
sectionShorts2 = 0
sectionShorts2 := nz(sectionShorts2[1])

if longCond2
    sectionLongs2 += 1
    sectionShorts2 := 0
    sectionShorts2

if shortCond2
    sectionLongs2 := 0
    sectionShorts2 += 1
    sectionShorts2


// Count your long short conditions for more control with Pyramiding 3

sectionLongs3 = 0
sectionLongs3 := nz(sectionLongs3[1])
sectionShorts3 = 0
sectionShorts3 := nz(sectionShorts3[1])

if longCond3
    sectionLongs3 += 1
    sectionShorts3 := 0
    sectionShorts3

if shortCond3
    sectionLongs3 := 0
    sectionShorts3 += 1
    sectionShorts3

////////////////////////////////////////////////////////////    
// Pyramiding

pyrl = 1


// Pyramiding 2

pyr2 = 1

// Pyramiding 3

pyr3 = 1
////////////////////////////////////////////////////////////    

// These check to see your signal and cross references it against the pyramiding settings above


longCondition = longCond and sectionLongs <= pyrl
shortCondition = shortCond and sectionShorts <= pyrl

// These check to see your signal and cross references it against the pyramiding settings above 2


longCondition2 = longCond2 and sectionLongs2 <= pyr2
shortCondition2 = shortCond2 and sectionShorts2 <= pyr2

// These check to see your signal and cross references it against the pyramiding settings above 3


longCondition3 = longCond3 and sectionLongs3 <= pyr3
shortCondition3 = shortCond3 and sectionShorts3 <= pyr3

////////////////////////////////////////////////////////////    
// Get the price of the last opened long or short

last_open_longCondition = float(na)
last_open_shortCondition = float(na)
last_open_longCondition := longCondition ? open : nz(last_open_longCondition[1])
last_open_shortCondition := shortCondition ? open : nz(last_open_shortCondition[1])

// Get the price of the last opened long or short 2

last_open_longCondition2 = float(na)
last_open_shortCondition2 = float(na)
last_open_longCondition2 := longCondition2 ? open : nz(last_open_longCondition2[1])
last_open_shortCondition2 := shortCondition2 ? open : nz(last_open_shortCondition2[1])

// Get the price of the last opened long or short 3

last_open_longCondition3 = float(na)
last_open_shortCondition3 = float(na)
last_open_longCondition3 := longCondition3 ? open : nz(last_open_longCondition3[1])
last_open_shortCondition3 := shortCondition3 ? open : nz(last_open_shortCondition3[1])


////////////////////////////////////////////////////////////    
// Check if your last postion was a long or a short

last_longCondition = float(na)
last_shortCondition = float(na)
last_longCondition := longCondition ? time : nz(last_longCondition[1])
last_shortCondition := shortCondition ? time : nz(last_shortCondition[1])

in_longCondition = last_longCondition > last_shortCondition
in_shortCondition = last_shortCondition > last_longCondition

// Check if your last postion was a long or a short 2

last_longCondition2 = float(na)
last_shortCondition2 = float(na)
last_longCondition2 := longCondition2 ? time : nz(last_longCondition2[1])
last_shortCondition2 := shortCondition2 ? time : nz(last_shortCondition2[1])

in_longCondition2 = last_longCondition2 > last_shortCondition2
in_shortCondition2 = last_shortCondition2 > last_longCondition2

// Check if your last postion was a long or a short 3

last_longCondition3 = float(na)
last_shortCondition3 = float(na)
last_longCondition3 := longCondition3 ? time : nz(last_longCondition3[1])
last_shortCondition3 := shortCondition3 ? time : nz(last_shortCondition3[1])

in_longCondition3 = last_longCondition3 > last_shortCondition3
in_shortCondition3 = last_shortCondition3 > last_longCondition3


////////////////////////////////////////////////////////////    
// Take profit

isTPl = input(true, 'Take Profit Long')
isTPs = input(true, 'Take Profit Short')
tp = input(2, 'Take Profit %')
long_tp = isTPl and ta.crossover(high, (1 + tp / 100) * last_open_longCondition) and longCondition == 0 and in_longCondition == 1
short_tp = isTPs and ta.crossunder(low, (1 - tp / 100) * last_open_shortCondition) and shortCondition == 0 and in_shortCondition == 1

// Take profit 2

isTP2 = input(true, 'Take Profit Long 2')
isTPs2 = input(true, 'Take Profit Short 2')
tp2 = input(4.5, 'Take Profit 2 %')
long_tp2 = isTP2 and ta.crossover(high, (1 + tp2 / 100) * last_open_longCondition2) and longCondition2 == 0 and in_longCondition2 == 1
short_tp2 = isTPs2 and ta.crossunder(low, (1 - tp2 / 100) * last_open_shortCondition2) and shortCondition2 == 0 and in_shortCondition2 == 1

// Take profit 3

isTP3 = input(true, 'Take Profit Long 3')
isTPs3 = input(true, 'Take Profit Short 3')
tp3 = input.float(7, 'Take Profit %')
long_tp3 = isTP3 and ta.crossover(high, (1 + tp3 / 100) * last_open_longCondition) and longCondition == 0 and in_longCondition == 1
short_tp3 = isTPs3 and ta.crossunder(low, (1 - tp3 / 100) * last_open_shortCondition) and shortCondition == 0 and in_shortCondition == 1


////////////////////////////////////////////////////////////    
// Stop Loss

isSLl = input(false, 'Stop Loss Long')
isSLs = input(false, 'Stop Loss Short')
sl = 0.0
sl := input.float(3, 'Stop Loss %')
long_sl = isSLl and ta.crossunder(low, (1 - sl / 100) * last_open_longCondition) and longCondition == 0 and in_longCondition == 1
short_sl = isSLs and ta.crossover(high, (1 + sl / 100) * last_open_shortCondition) and shortCondition == 0 and in_shortCondition == 1

// Stop Loss 2

isSLl2 = input(false, 'Stop Loss Long 2')
isSLs2 = input(false, 'Stop Loss short 2')
sl2 = 0.0
sl2 := input.float(3, 'Stop Loss %')
long_sl2 = isSLl2 and ta.crossunder(low, (1 - sl2 / 100) * last_open_longCondition2) and longCondition2 == 0 and in_longCondition2 == 1
short_sl2 = isSLs2 and ta.crossover(high, (1 + sl2 / 100) * last_open_shortCondition2) and shortCondition2 == 0 and in_shortCondition2 == 1

////////////////////////////////////////////////////////////    
// Create a single close for all the different closing conditions.

long_close = long_tp or long_sl ? 1 : 0
short_close = short_tp or short_sl ? 1 : 0


// Create a single close for all the different closing conditions 2

long_close2 = long_tp2 or long_sl2 ? 1 : 0
short_close2 = short_tp2 or short_sl2 ? 1 : 0

// Create a single close for all the different closing conditions. 3

long_close3 = long_tp3 ? 1 : 0
short_close3 = short_tp3 ? 1 : 0


////////////////////////////////////////////////////////////    
// Get the time of the last close

last_long_close = float(na)
last_short_close = float(na)
last_long_close := long_close ? time : nz(last_long_close[1])
last_short_close := short_close ? time : nz(last_short_close[1])

// Get the time of the last close 2

last_long_close2 = float(na)
last_short_close2 = float(na)
last_long_close2 := long_close2 ? time : nz(last_long_close2[1])
last_short_close2 := short_close2 ? time : nz(last_short_close2[1])

// Get the time of the last close 3

last_long_close3 = float(na)
last_short_close3 = float(na)
last_long_close3 := long_close3 ? time : nz(last_long_close3[1])
last_short_close3 := short_close3 ? time : nz(last_short_close3[1])

////////////////////////////////////////////////////////////    
//Signals 

bton(b) =>
    b ? 1 : 0
//
plotchar(long_tp and last_longCondition > nz(last_long_close[1]), text='TP1', title='Take Profit Long', size=size.tiny, location=location.abovebar, color=color.new(color.green, 0))
plotchar(long_tp2 and last_longCondition2 > nz(last_long_close2[1]), text='TP2', title='Take Profit Long 2', size=size.tiny, location=location.abovebar, color=color.new(color.green, 0))
//
plotchar(short_tp and last_shortCondition > nz(last_short_close[1]), text='TP1', title='Take Profit Short', size=size.tiny, location=location.belowbar, color=color.new(color.red, 0))
plotchar(short_tp2 and last_shortCondition2 > nz(last_short_close2[1]), text='TP2', title='Take Profit Short 2', size=size.tiny, location=location.belowbar, color=color.new(color.red, 0))
//
plotchar(long_tp3 and last_longCondition3 > nz(last_long_close3[1]), text='TP3', title='Take Profit Long', size=size.tiny, location=location.abovebar, color=color.new(color.green, 0))
plotchar(short_tp3 and last_shortCondition3 > nz(last_short_close3[1]), text='TP3', title='Take Profit Short', size=size.tiny, location=location.belowbar, color=color.new(color.red, 0))
//
ltp = long_tp and last_longCondition > nz(last_long_close[1]) ? (1 + tp / 100) * last_open_longCondition : na
plot(ltp, color=color.new(color.green, 100), trackprice=true, style=plot.style_linebr, linewidth=2 , title = "Take profit - 1")
//stp = short_tp and last_shortCondition > nz(last_short_close[1]) ? (1 - tp / 100) * last_open_shortCondition : na
//plot(stp, style=plot.style_linebr, trackprice=true, linewidth=3, color=color.new(color.white, 0))
//
ltp2 = long_tp2 and last_longCondition2 > nz(last_long_close2[1]) ? (1 + tp2 / 100) * last_open_longCondition2 : na
plot(ltp2, color=color.new(color.green, 100), trackprice=true, style=plot.style_linebr, linewidth=2, title = "Take profit - 2")
//stp2 = short_tp2 and last_shortCondition2 > nz(last_short_close2[1]) ? (1 - tp2 / 100) * last_open_shortCondition2 : na
//plot(stp2, style=plot.style_linebr, trackprice=true, linewidth=3, color=color.new(color.white, 0))
//
ltp3 = long_tp3 and last_longCondition3 > nz(last_long_close3[1]) ? (1 + tp3 / 100) * last_open_longCondition3 : na
plot(ltp3, color=color.new(color.green, 100), trackprice=true, style=plot.style_linebr, linewidth=2, title = "Take profit - 3")
//stp3 = short_tp3 and last_shortCondition3 > nz(last_short_close3[1]) ? (1 - tp3 / 100) * last_open_shortCondition3 : na
//plot(stp3, style=plot.style_linebr, trackprice=true, linewidth=3, color=color.new(color.white, 0))
//

//Stoploss 1 plotchar
plotchar(long_sl and last_longCondition > nz(last_long_close[1]), char='⛔', text='SL1 LONG', title='Stop Loss Long', size=size.tiny, location=location.abovebar, color=color.new(color.red, 0))
plotchar(short_sl and last_shortCondition > nz(last_short_close[1]), char='⛔', text='SL1 SHORT', title='Stop Loss Short', size=size.tiny, location=location.belowbar, color=color.new(color.red, 0))

//lsl = long_sl and last_longCondition > nz(last_long_close[1]) ? (1 - sl / 100) * last_open_longCondition : na
//plot(lsl, style=plot.style_linebr, linewidth=3, color=color.new(color.white, 0))
//ssl = short_sl and last_shortCondition > nz(last_short_close[1]) ? (1 + sl / 100) * last_open_shortCondition : na
//plot(ssl, style=plot.style_linebr, linewidth=3, color=color.new(color.white, 0))

//Stoploss 2 plotchar
plotchar(long_sl2 and last_longCondition2 > nz(last_long_close2[1]), char='⛔', text='SL2 LONG', title='Stop Loss Long 2', size=size.tiny, location=location.abovebar, color=color.new(color.red, 0))
plotchar(short_sl2 and last_shortCondition2 > nz(last_short_close2[1]), char='⛔', text='SL2 SHORT', title='Stop Loss Short 2', size=size.tiny, location=location.belowbar, color=color.new(color.red, 0))

lsl2 = long_sl2 and last_longCondition2 > nz(last_long_close2[1]) ? (1 - sl2 / 100) * last_open_longCondition2 : na
//plot(lsl2, style=plot.style_linebr, linewidth=3, color=color.new(color.white, 0))
//ssl2 = short_sl2 and last_shortCondition2 > nz(last_short_close2[1]) ? (1 + sl2 / 100) * last_open_shortCondition2 : na
//plot(ssl2, style=plot.style_linebr, linewidth=3, color=color.new(color.white, 0))

//plot for trend
//plot(dir == 1 ? longStop : na, title="BuyLine", style=linebr, linewidth=2, color=longColor)
plotshape(dir == 1 and dir[1] == -1 ? longStop : na, title='LONG', style=shape.triangleup, location=location.belowbar, size=size.small, text='LONG', textcolor=color.new(color.green, 0), color=color.new(color.green, 0))
//plot(dir == 1 ? na : shortStop, title="SellLine", style=linebr, linewidth=2, color=shortColor)
plotshape(dir == -1 and dir[1] == 1 ? shortStop : na, title='SHORT', style=shape.triangledown, location=location.abovebar, size=size.small, text='SHORT', textcolor=color.new(color.red, 0), color=color.new(color.red, 0))

//kumo plots
//plot(conversionLine, color=#0496ff, title="Conversion Line")
//plot(baseLine, color=#991515, title="Base Line")
//plot(close, offset = -displacement, color=#459915, title="Lagging Span")
//K1 = plot(leadLine1, offset=displacement, color=color.new(color.green, 0), title='Lead 1')
//K2 = plot(leadLine2, offset=displacement, color=color.new(color.red, 0), title='Lead 2')
//fill(K1, K2, leadLine1 > leadLine2 ? color.green : color.red, transp=90)

//barcolor(dir == 1 ? color.green : color.red)



//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Functions
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Conditional Sampling EMA Function 
Cond_EMA(x, cond, n) =>
    var val = array.new_float(0)
    var ema_val = array.new_float(1)
    if cond
        array.push(val, x)
        if array.size(val) > 1
            array.remove(val, 0)
        if na(array.get(ema_val, 0))
            array.fill(ema_val, array.get(val, 0))
        array.set(ema_val, 0, (array.get(val, 0) - array.get(ema_val, 0)) * (2 / (n + 1)) + array.get(ema_val, 0))
    EMA = array.get(ema_val, 0)
    EMA

//Conditional Sampling SMA Function
Cond_SMA(x, cond, n) =>
    var vals = array.new_float(0)
    if cond
        array.push(vals, x)
        if array.size(vals) > n
            array.remove(vals, 0)
    SMA = array.avg(vals)
    SMA

//Standard Deviation Function
Stdev(x, n) =>
    math.sqrt(Cond_SMA(math.pow(x, 2), 1, n) - math.pow(Cond_SMA(x, 1, n), 2))

//Range Size Function
rng_size(x, scale, qty, n) =>
    ATR = Cond_EMA(ta.tr(true), 1, n)
    AC = Cond_EMA(math.abs(x - x[1]), 1, n)
    SD = Stdev(x, n)
    rng_size = scale == 'Pips' ? qty * 0.0001 : scale == 'Points' ? qty * syminfo.pointvalue : scale == '% of Price' ? close * qty / 100 : scale == 'ATR' ? qty * ATR : scale == 'Average Change' ? qty * AC : scale == 'Standard Deviation' ? qty * SD : scale == 'Ticks' ? qty * syminfo.mintick : qty
    rng_size

//Two Type Range Filter Function
rng_filt(h, l, rng_, n, type, smooth, sn, av_rf, av_n) =>
    rng_smooth = Cond_EMA(rng_, 1, sn)
    r = smooth ? rng_smooth : rng_
    var rfilt = array.new_float(2, (h + l) / 2)
    array.set(rfilt, 1, array.get(rfilt, 0))
    if type == 'Type 1'
        if h - r > array.get(rfilt, 1)
            array.set(rfilt, 0, h - r)
        if l + r < array.get(rfilt, 1)
            array.set(rfilt, 0, l + r)
    if type == 'Type 2'
        if h >= array.get(rfilt, 1) + r
            array.set(rfilt, 0, array.get(rfilt, 1) + math.floor(math.abs(h - array.get(rfilt, 1)) / r) * r)
        if l <= array.get(rfilt, 1) - r
            array.set(rfilt, 0, array.get(rfilt, 1) - math.floor(math.abs(l - array.get(rfilt, 1)) / r) * r)
    rng_filt1 = array.get(rfilt, 0)
    hi_band1 = rng_filt1 + r
    lo_band1 = rng_filt1 - r
    rng_filt2 = Cond_EMA(rng_filt1, rng_filt1 != rng_filt1[1], av_n)
    hi_band2 = Cond_EMA(hi_band1, rng_filt1 != rng_filt1[1], av_n)
    lo_band2 = Cond_EMA(lo_band1, rng_filt1 != rng_filt1[1], av_n)
    rng_filt = av_rf ? rng_filt2 : rng_filt1
    hi_band = av_rf ? hi_band2 : hi_band1
    lo_band = av_rf ? lo_band2 : lo_band1
    [hi_band, lo_band, rng_filt]

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Inputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Filter Type
f_type = input.string(defval='Type 1', options=['Type 1', 'Type 2'], title='Filter Type')

//Movement Source
mov_src = input.string(defval='Close', options=['Wicks', 'Close'], title='Movement Source')

//Range Size Inputs
rng_qty = input.float(defval=8, minval=0.0000001, title='Range Size')
rng_scale = input.string(defval='Average Change', options=['Points', 'Pips', 'Ticks', '% of Price', 'ATR', 'Average Change', 'Standard Deviation', 'Absolute'], title='Range Scale')

//Range Period
rng_per = input.int(defval=40, minval=1, title='Range Period (for ATR, Average Change, and Standard Deviation)')

//Range Smoothing Inputs
smooth_range = input(defval=true, title='Smooth Range')
smooth_per = input.int(defval=150, minval=1, title='Smoothing Period')

//Filter Value Averaging Inputs
av_vals = input(defval=false, title='Average Filter Changes')
av_samples = input.int(defval=2, minval=1, title='Number Of Changes To Average')

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Definitions
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//High And Low Values
h_val = mov_src == 'Wicks' ? high : close
l_val = mov_src == 'Wicks' ? low : close

//Range Filter Values
[h_band, l_band, filt] = rng_filt(h_val, l_val, rng_size((h_val + l_val) / 2, rng_scale, rng_qty, rng_per), rng_per, f_type, smooth_range, smooth_per, av_vals, av_samples)

//Direction Conditions
var fdir = 0.0
fdir := filt > filt[1] ? 1 : filt < filt[1] ? -1 : fdir
upward = fdir == 1 ? 1 : 0
downward = fdir == -1 ? 1 : 0

//Colors
filt_color = upward ? #05ff9b : downward ? #ff0583 : #cccccc

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Outputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Filter Plot
filt_plot = plot(filt, color=dir == 1 ? color.green : color.red, linewidth=3, title='Trend Line', transp=0)


//Alerts

alertcondition(dir == 1 and dir[1] == -1 ? longStop : na, title='Buy', message='Buy!')
alertcondition(dir == 1 and dir[1] == -1 ? longStop : na, title='Buy', message='Buy!')
alertcondition(dir == 1 and dir[1] == -1 ? longStop : na, title='Buy', message='Buy!')
alertcondition(dir == -1 and dir[1] == 1 ? shortStop : na, title='Sell', message='Sell!')
//TP1 & SL1
alertcondition(bton(long_tp and last_longCondition > nz(last_long_close[1])), title='TP1 LONG')
alertcondition(bton(short_tp and last_shortCondition > nz(last_short_close[1])), title='TP1 SHORT')
alertcondition(bton(long_sl and last_longCondition > nz(last_long_close[1])), title='SL1 LONG')
alertcondition(bton(short_sl and last_shortCondition > nz(last_short_close[1])), title='SL1 SHORT')
//TP2 & SL2
alertcondition(bton(long_tp2 and last_longCondition2 > nz(last_long_close2[1])), title='TP2 LONG')
alertcondition(bton(short_tp2 and last_shortCondition2 > nz(last_short_close2[1])), title='TP2 SHORT')
alertcondition(bton(long_sl2 and last_longCondition2 > nz(last_long_close2[1])), title='SL2 LONG')
alertcondition(bton(short_sl2 and last_shortCondition2 > nz(last_short_close2[1])), title='SL2 SHORT')
//TP3
alertcondition(bton(long_tp3 and last_longCondition3 > nz(last_long_close3[1])), title='TP3 LONG')
alertcondition(bton(short_tp3 and last_shortCondition3 > nz(last_short_close3[1])), title='TP3 SHORT')

